<?php

namespace WebmanGrpc;

/**
 * Webman gRPC扩展包主入口类
 * 
 * 提供gRPC服务端和客户端的核心功能，包括：
 * - 服务注册与发现
 * - 请求处理与响应
 * - 连接池管理
 * - HTTP到gRPC的转换
 * - 拦截器支持
 */
class Grpc
{
    /**
     * 版本号
     */
    const VERSION = '1.0.0';
    
    /**
     * 默认配置
     */
    const DEFAULT_CONFIG = [
        'server' => [
            'host' => '0.0.0.0',
            'port' => 50051,
            'credentials' => null,
            'max_recv_msg_length' => 4194304,
            'max_send_msg_length' => 4194304,
        ],
        'client' => [
            'timeout' => 30,
            'credentials' => null,
            'max_recv_msg_length' => 4194304,
            'max_send_msg_length' => 4194304,
            'retry' => 3,
            'backoff' => [
                'initial' => 100,
                'max' => 1000,
                'multiplier' => 2,
            ],
            'connection_pool' => [
                'max_connections' => 10,
                'idle_timeout' => 60,
                'max_lifetime' => 300,
            ],
        ],
        'http_gateway' => [
            'enabled' => true,
            'routes' => [],
            'transformers' => [],
        ],
    ];
    
    /**
     * 已注册的服务
     */
    protected static array $services = [];
    
    /**
     * 拦截器
     */
    protected static array $interceptors = [];
    
    /**
     * 配置
     */
    protected static array $config = [];
    
    /**
     * 初始化gRPC扩展
     * 
     * @param array $config 配置参数
     * @return void
     */
    public static function init(array $config = []): void
    {
        // 合并默认配置
        self::$config = array_merge_recursive(self::DEFAULT_CONFIG, $config);
        
        // 检查gRPC扩展是否已安装
        if (!extension_loaded('grpc')) {
            throw new \RuntimeException('gRPC extension is not installed');
        }
        
        // 检查protobuf扩展是否已安装
        if (!extension_loaded('protobuf')) {
            throw new \RuntimeException('protobuf extension is not installed');
        }
    }
    
    /**
     * 注册gRPC服务
     * 
     * @param string $serviceName 服务名称
     * @param string $className 实现类名
     * @param array $options 服务选项
     * @return void
     */
    public static function registerService(string $serviceName, string $className, array $options = []): void
    {
        if (!class_exists($className)) {
            throw new \InvalidArgumentException("Service class {$className} not found");
        }
        
        self::$services[$serviceName] = [
            'class' => $className,
            'options' => $options,
        ];
    }
    
    /**
     * 获取已注册的服务
     * 
     * @return array 已注册的服务列表
     */
    public static function getServices(): array
    {
        return self::$services;
    }
    
    /**
     * 添加拦截器
     * 
     * @param string $interceptorClass 拦截器类名
     * @param int $priority 优先级，数字越小优先级越高
     * @return void
     */
    public static function addInterceptor(string $interceptorClass, int $priority = 100): void
    {
        if (!class_exists($interceptorClass)) {
            throw new \InvalidArgumentException("Interceptor class {$interceptorClass} not found");
        }
        
        self::$interceptors[$priority][] = $interceptorClass;
        ksort(self::$interceptors);
    }
    
    /**
     * 获取拦截器列表
     * 
     * @return array 拦截器列表
     */
    public static function getInterceptors(): array
    {
        $result = [];
        foreach (self::$interceptors as $priorityGroup) {
            $result = array_merge($result, $priorityGroup);
        }
        return $result;
    }
    
    /**
     * 获取配置
     * 
     * @param string|null $key 配置键，为null时返回所有配置
     * @param mixed $default 默认值
     * @return mixed 配置值
     */
    public static function getConfig(?string $key = null, $default = null)
    {
        if ($key === null) {
            return self::$config;
        }
        
        return self::getConfigValue($key, self::$config, $default);
    }
    
    /**
     * 递归获取配置值
     * 
     * @param string $key 配置键，支持点号分隔的多级键
     * @param array $config 配置数组
     * @param mixed $default 默认值
     * @return mixed 配置值
     */
    protected static function getConfigValue(string $key, array $config, $default = null)
    {
        $keys = explode('.', $key);
        $value = $config;
        
        foreach ($keys as $k) {
            if (!is_array($value) || !array_key_exists($k, $value)) {
                return $default;
            }
            $value = $value[$k];
        }
        
        return $value;
    }
    
    /**
     * 创建gRPC服务器
     * 
     * @param array $options 服务器选项
     * @return \Grpc\Server gRPC服务器实例
     */
    public static function createServer(array $options = []): \Grpc\Server
    {
        $serverOptions = array_merge(self::$config['server'], $options);
        
        $server = new \Grpc\Server();
        
        // 设置服务器选项
        if (isset($serverOptions['max_recv_msg_length'])) {
            $server->setMaxRecvMessageLength($serverOptions['max_recv_msg_length']);
        }
        
        if (isset($serverOptions['max_send_msg_length'])) {
            $server->setMaxSendMessageLength($serverOptions['max_send_msg_length']);
        }
        
        return $server;
    }
    
    /**
     * 创建gRPC客户端
     * 
     * @param string $address 服务地址
     * @param array $options 客户端选项
     * @return \Grpc\Channel gRPC通道实例
     */
    public static function createClient(string $address, array $options = []): \Grpc\Channel
    {
        $clientOptions = array_merge(self::$config['client'], $options);
        
        // 设置凭证
        $credentials = null;
        if (isset($clientOptions['credentials']) && $clientOptions['credentials'] !== null) {
            $credentials = $clientOptions['credentials'];
        }
        
        return new \Grpc\Channel($address, $credentials, $clientOptions);
    }
}